DP Tensor Experiment - v8

Purpose:

Conclusions:

simple change - time to vectorize!


In [1]:
from collections import Counter
import numpy as np

class PrivateNumber():
    
    def __init__(self, value, max_val, min_val):
        self.value = value
        self.max_val = max_val
        self.min_val = min_val
        
    def __add__(self, other):
        
        # add to a private number
        
        if(isinstance(other, PrivateNumber)):

            entities = self.entities.union(other.entities)
            
            new_val = self.value + other.value

            entities = set(self.max_val.keys()).union(set(other.max_val.keys()))

            new_max_val = {}
            new_min_val = {}
            for entity in entities:
                
                self_max = self.max_val[entity] if entity in self.max_val else 0
                other_max = other.max_val[entity] if entity in other.max_val else 0
                
                self_min = self.min_val[entity] if entity in self.min_val else 0
                other_min = other.min_val[entity] if entity in other.min_val else 0
                
                new_max_val[entity] = self_max + other_max
                new_min_val[entity] = self_min + other_min

        else:

            entities = self.entities

            # add to a public number
            new_val = self.value + other
            
            new_max_val = {}
            new_min_val = {}
            for entity in entities:
                new_max_val[entity] = self.max_val[entity] + other
                new_min_val[entity] = self.min_val[entity] + other

        return PrivateNumber(new_val,
                             new_max_val,
                             new_min_val)
    
    def __mul__(self, other):
        
        if(isinstance(other, PrivateNumber)):
        
            new_self_max_val = {}
            new_self_min_val = {}
            for entity in self.entities:
                
                # the biggest positive number this entity could contribute is when
                # it is multiplied by the largest value of the same sign from other
                new_self_max_val[entity] = max(self.min_val[entity] * other.xmin, 
                                               self.max_val[entity] * other.xmax)
                
                # the smallest negative number this entity could contribute is when
                # it is multiplied by the largest value of the opposite sign from other
                new_self_min_val[entity] = min(self.min_val[entity] * other.xmax,
                                               self.max_val[entity] * other.xmin)
                
            new_other_max_val = {}
            new_other_min_val = {}
            for entity in other.entities:
                
                # the biggest positive number this entity could contribute is when
                # it is multiplied by the largest value of the same sign from other
                new_other_max_val[entity] = max(other.min_val[entity] * self.xmin, 
                                                other.max_val[entity] * self.xmax)
                
                # the smallest negative number this entity could contribute is when
                # it is multiplied by the largest value of the opposite sign from other
                new_other_min_val[entity] = min(other.min_val[entity] * self.xmax,
                                                other.max_val[entity] * self.xmin)
                
            new_max_val = {}
            new_min_val = {}
            
            for entity in self.entities:
                
                left = new_self_max_val[entity] if entity in new_self_max_val else -(2**32)
                right = new_other_max_val[entity] if entity in new_other_max_val else -(2**32)
                
                new_max_val[entity] = max(left, right)
                
                left = new_self_min_val[entity] if entity in new_self_min_val else 2**32
                right = new_other_min_val[entity] if entity in new_other_min_val else 2**32
                
                new_min_val[entity] = min(left, right)

            return PrivateNumber(self.value * other.value,
                                    new_max_val,
                                    new_min_val)
            
    
        new_max_val = {}
        for entity in self.entities:
            new_max_val[entity] = self.max_val[entity] * other

        new_min_val = {}
        for entity in self.entities:
            new_min_val[entity] = self.min_val[entity] * other
        
        if(other > 0):
            return PrivateNumber(self.value * other,
                                    new_max_val,
                                    new_min_val)
        else:
            return PrivateNumber(self.value * other,
                                    new_min_val,                                 
                                    new_max_val)
    
    def __neg__(self):
        return self * -1
    
    def __sub__(self, other):
        return self + (-other)

    def __gt__(self, other):

        if(isinstance(other, PrivateNumber)):
        
            new_self_max_val = {}
            new_self_min_val = {}
            for entity in self.entities:
                
                if not (self.min_val[entity] > other.xmax or self.max_val[entity] < other.xmin):
                    new_self_max_val[entity] = 1
                else:
                    new_self_max_val[entity] = 0
                
                new_self_min_val[entity] = 0
                
            new_other_max_val = {}
            new_other_min_val = {}
            for entity in other.entities:
                
                if not (other.min_val[entity] > self.xmax or other.max_val[entity] < self.xmin):
                    new_other_max_val[entity] = 1
                else:
                    new_other_max_val[entity] = 0
                    
                new_other_min_val[entity] = 0
                
            new_max_val = {}
            new_min_val = {}
            
            entities = self.entities.union(other.entities)
                
            for entity in entities:
                
                new_self_max = new_self_max_val[entity] if entity in new_self_max_val else -999999999
                new_other_max = new_other_max_val[entity] if entity in new_other_max_val else -999999999
                
                new_self_min = new_self_min_val[entity] if entity in new_self_min_val else 99999999
                new_other_min = new_other_min_val[entity] if entity in new_other_min_val else 99999999
                
                new_max_val[entity] = max(new_self_max, new_other_max)
                new_min_val[entity] = min(new_self_min, new_other_min)

            result = int(self.value > other.value)
        else:

            entities = self.entities.union(other.entities)

            new_max_val = {}
            new_min_val = {}
            for entity in entities:

                new_min_val[entity] = 0

                if(other <= self.max_val[entity] and other >= self.min_val[entity]):    
                    new_max_val[entity] = 1
                else:
                    new_max_val[entity] = 0

            result = int(self.value > other)
            
        return PrivateNumber(result,
                                new_max_val,
                                new_min_val)
    
    def __lt__(self, other):
        
        if(isinstance(other, PrivateNumber)):
        
            entities = self.entities.union(other.entities)
        
            new_self_max_val = {}
            new_self_min_val = {}
            
            for entity in self.entities:
                
                if not (self.min_val[entity] > other.xmax or self.max_val[entity] < other.xmin):
                    new_self_max_val[entity] = 1
                else:
                    new_self_max_val[entity] = 0
                
                new_self_min_val[entity] = 0
                
            new_other_max_val = {}
            new_other_min_val = {}
            
            for entity in other.entities:
                
                if not (other.min_val[entity] > self.xmax or other.max_val[entity] < self.xmin):
                    new_other_max_val[entity] = 1
                else:
                    new_other_max_val[entity] = 0
                    
                new_other_min_val[entity] = 0
                
            new_max_val = {}
            new_min_val = {}
            
            entities = self.entities.union(other.entities)
                
            for entity in entities:
                
                new_self_max = new_self_max_val[entity] if entity in new_self_max_val else -999999999
                new_other_max = new_other_max_val[entity] if entity in new_other_max_val else -999999999
                
                new_self_min = new_self_min_val[entity] if entity in new_self_min_val else 99999999
                new_other_min = new_other_min_val[entity] if entity in new_other_min_val else 99999999
                
                new_max_val[entity] = max(new_self_max, new_other_max)
                new_min_val[entity] = min(new_self_min, new_other_min)

            result = int(self.value < other.value)
        
        else:

            entities = self.entities

            new_max_val = {}
            new_min_val = {}
            for entity in entities:

                new_min_val[entity] = 0

                if(other <= self.max_val[entity] and other >= self.min_val[entity]):    
                    new_max_val[entity] = 1
                else:
                    new_max_val[entity] = 0

            result = int(self.value < other)
        
        return PrivateNumber(result,
                             new_max_val,
                             new_min_val)
    
    def max(self, other):
        
        if(isinstance(other, PrivateNumber)):
            raise Exception("Not implemented yet")
        
        entities = self.entities
        
        new_min_val = {}
        for entity in entities:
            new_min_val[entity] = max(self.min_val[entity], other)
            
        return PrivateNumber(max(self.value, other),
                                self.max_val,
                                new_min_val)
    
    def min(self, other):
        
        if(isinstance(other, PrivateNumber)):
            raise Exception("Not implemented yet")
        
        entities = self.entities
        
        new_max_val = {}
        for entity in entities:
            new_max_val[entity] = min(self.max_val[entity], other)
                
        return PrivateNumber(min(self.value, other),
                                new_max_val,
                                self.min_val)
    
    def __repr__(self):
        return str(self.value) + " " + str(self.max_val) + " " + str(self.min_val)
    
    def hard_sigmoid(self):
        return self.min(1).max(0)
    
    def hard_sigmoid_deriv(self):
        return ((self < 1) * (self > 0)) + (self < 0) * 0.01 - (self > 1) * 0.01
    
    @property
    def xmin(self):
        items = list(self.min_val.items())
        out = items[0][1]
        for k,v in items[1:]:
            out += v
        return out
    
    @property
    def xmax(self):
        items = list(self.max_val.items())
        out = items[0][1]
        for k,v in items[1:]:
            out += v
        return out
    
    @property
    def entities(self):
        return set(self.max_val.keys())
    
    @property
    def max_sensitivity(self):
        sens = Counter()
        for entity, value in self.max_val.items():
            sens[entity] = value - self.min_val[entity]
        return sens.most_common()[0][1]

In [2]:
x = PrivateNumber(0.5,{"bob":4, "amos":3},{"bob":3, "amos":2})
x2 = PrivateNumber(0.5,{"bob":4, "amos":3},{"bob":3, "amos":2})
y = PrivateNumber(1,{"bob":1},{"bob":-1})
z = PrivateNumber(-0.5,{"sue":2},{"sue":-1})

In [4]:
x


Out[4]:
0.5 {'bob': 4, 'amos': 3} {'bob': 3, 'amos': 2}

In [ ]:


In [78]:
a = (x * x2)# > y

In [79]:
a


Out[79]:
0.25 {'bob': 28, 'amos': 21} {'bob': 20, 'amos': 14}

In [69]:
a.max_sensitivity


Out[69]:
0

In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]: